//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <elacfg.h>
#include "CCallbackContext.h"

extern PInterface g_pMainCallbackContext;

EXTERN ExitCode _Impl_CallbackSink_TryToHandleEvents()
{
    CCallbackContext *pCallbackContext = NULL;

    _CThread_GetLocalObject(TL_CALLBACK_SLOT, (PInterface *)&pCallbackContext);

    if (NULL == pCallbackContext) return 0;

    ExitCode ec = pCallbackContext->HandleCallbackEvents();
    pCallbackContext->m_Status = AppletStatus_Finishing;

    pCallbackContext->Release();

    return ec;
}

ELAPI _Impl_CallbackSink_GetCallbackContext(
    PInterface *ppCallbackContext)
{
    if (NULL == ppCallbackContext) return E_INVALID_ARGUMENT;

    CCallbackContext *pCallbackContext;

    _CThread_GetLocalObject(TL_CALLBACK_SLOT, (PInterface *)&pCallbackContext);

    if (NULL == pCallbackContext) return E_NOT_CALLBACK_THREAD;

    *ppCallbackContext = pCallbackContext;
    return NOERROR;
}

ELAPI _Impl_CallbackSink_SetDefaultCallbackContext(
    PInterface pCallbackContext)
{
    g_pMainCallbackContext = pCallbackContext;
    return NOERROR;
}

ELAPI _Impl_CallbackSink_GetDefaultCallbackContext(
    PInterface *ppCallbackContext)
{
    assert(ppCallbackContext);
    if (g_pMainCallbackContext) g_pMainCallbackContext->AddRef();
    *ppCallbackContext = g_pMainCallbackContext;
    return NOERROR;
}

ELAPI _Impl_CallbackSink_InitCallbackContext(
    PInterface *ppCallbackContext)
{
    CCallbackContext *pCallbackContext;

    pCallbackContext = new CCallbackContext();
    if (NULL == pCallbackContext) return E_OUT_OF_MEMORY;

    pCallbackContext->AddRef();

    ECode ec = pCallbackContext->Initialize();
    if (FAILED(ec)) {
        pCallbackContext->Release();
        return ec;
    }

    _CThread_SetLocalObject(TL_CALLBACK_SLOT, pCallbackContext);

    if (NULL != ppCallbackContext) {
        pCallbackContext->AddRef();
        *ppCallbackContext = pCallbackContext;
    }

    return NOERROR;
}

ELAPI _Impl_CallbackSink_AcquireCallbackContext(PInterface *ppCallbackContext)
{
    CCallbackContext *pCallbackContext;
    ECode ec;

    if (NULL == ppCallbackContext) return E_INVALID_ARGUMENT;

    _CThread_GetLocalObject(TL_ORG_CALLBACK_SLOT, ppCallbackContext);
    if (*ppCallbackContext) return NOERROR;

    pCallbackContext = new CCallbackContext();
    if (NULL == pCallbackContext) return E_OUT_OF_MEMORY;

    ec = pCallbackContext->Initialize();
    if (FAILED(ec)) return ec;

    pCallbackContext->AddRef();
    *ppCallbackContext = pCallbackContext;

    return NOERROR;
}

ELAPI _Impl_CallbackSink_PostCallbackEvent(
    IInterface *pCallbackContext,
    PCallbackEvent pCallbackEvent)
{
    if (NULL == pCallbackContext || NULL == pCallbackEvent) {
        return E_INVALID_ARGUMENT;
    }

    return ((CCallbackContext *)pCallbackContext)->
                PostCallbackEvent(pCallbackEvent);
}

ELAPI _Impl_CallbackSink_SendCallbackEvent(
    IInterface *pCallbackContext,
    PCallbackEvent pCallbackEvent,
    Millisecond32 msTimeOut)
{
    if (NULL == pCallbackContext || NULL == pCallbackEvent) {
        return E_INVALID_ARGUMENT;
    }

    return ((CCallbackContext *)pCallbackContext)->
                SendCallbackEvent(pCallbackEvent, msTimeOut);
}

ELAPI _Impl_CallbackSink_WaitForCallbackEvent(
    IInterface *pCallbackContext,
    Millisecond32 msTimeOut,
    WaitResult* pResult,
    Boolean * pbEventOccured,
    Flags32 fPriority)
{
    if (NULL == pCallbackContext) {
        return E_INVALID_ARGUMENT;
    }

    return ((CCallbackContext *)pCallbackContext)->
        HandleCallbackEvents(msTimeOut, pResult, pbEventOccured, fPriority);
}

ELAPI _Impl_CallbackSink_CleanupAllCallbacks(
    IInterface *pCallbackContext)
{
    if (NULL == pCallbackContext) return E_INVALID_ARGUMENT;

    ((CCallbackContext *)pCallbackContext)->CancelAllCallbackEvents();
    return NOERROR;
}

ELAPI _Impl_CallbackSink_CancelAllPendingCallbacks(
    IInterface *pCallbackContext,
    PInterface pSender)
{
    if (NULL == pCallbackContext) return E_INVALID_ARGUMENT;

    return ((CCallbackContext *)pCallbackContext)->
                CancelAllPendingCallbacks(pSender);
}

ELAPI _Impl_CallbackSink_CancelPendingCallback(
    IInterface *pCallbackContext,
    PInterface pSender,
    CallbackEventId id)
{
    if (NULL == pCallbackContext) return E_INVALID_ARGUMENT;

    return ((CCallbackContext *)pCallbackContext)->
                CancelPendingCallback(pSender, id);
}

ELAPI _Impl_CallbackSink_CancelCallbackEvents(
    IInterface *pCallbackContext,
    PInterface pSender,
    CallbackEventId id,
    PVoid pHandlerThis,
    PVoid pHandlerFunc)
{
    if (NULL == pCallbackContext) return E_INVALID_ARGUMENT;

    return ((CCallbackContext *)pCallbackContext)->
                CancelCallbackEvents(pSender, id, pHandlerThis, pHandlerFunc);
}

ELAPI _Impl_CallbackSink_RequestToFinish(
    PInterface pCallbackContext, AppletFinish Flag)
{
    CCallbackContext* pContext;
    ECode ec;
    if (pCallbackContext == NULL) {
        ec = _Impl_CallbackSink_GetCallbackContext((PInterface*)&pContext);
        if (FAILED(ec)) return ec;
        ec = pContext->RequestToFinish(Flag);
        pContext->Release();
    }
    else {
        pContext = (CCallbackContext*)pCallbackContext;
        ec = pContext->RequestToFinish(Flag);
    }
    return ec;
}

ELAPI _Impl_CallbackSink_GetThreadEvent(
    PInterface pCallbackContext,
    IEvent** ppEvent)
{
    if (NULL == pCallbackContext || NULL == ppEvent) {
        return E_INVALID_ARGUMENT;
    }

    ((CCallbackContext *)pCallbackContext)->m_pThreadEvent->AddRef();
    *ppEvent =  ((CCallbackContext *)pCallbackContext)->m_pThreadEvent;

    return NOERROR;
}

ELAPI_(AppletStatus) _Impl_CallbackSink_GetStatus(
    PInterface pCallbackContext)
{
    if (pCallbackContext) {
        return ((CCallbackContext *)pCallbackContext)->m_Status;
    }
    return 0;
}


